package com.xuecheng.learning.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xuecheng.base.constant.LearningChooseCourseStatusConstant;
import com.xuecheng.base.constant.LearningOrderTypeConstant;
import com.xuecheng.base.constant.LearningQualificationConstant;
import com.xuecheng.base.model.PageResult;
import com.xuecheng.base.util.SecurityUtil;
import com.xuecheng.learning.mapper.XcChooseCourseMapper;
import com.xuecheng.learning.mapper.XcCourseTablesMapper;
import com.xuecheng.learning.model.dto.MyCourseTableParams;
import com.xuecheng.learning.model.dto.XcCourseTablesDTO;
import com.xuecheng.learning.model.po.XcChooseCourse;
import com.xuecheng.learning.model.po.XcCourseTables;
import com.xuecheng.learning.service.IXcCourseTablesService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 勾新杰
 * @since 2025-02-26
 */
@Service
@RequiredArgsConstructor
public class XcCourseTablesServiceImpl extends ServiceImpl<XcCourseTablesMapper, XcCourseTables> implements IXcCourseTablesService {

    private final XcChooseCourseMapper xcChooseCourseMapper;

    private static final Integer REMAIN_EXPIRE_DAYS = 20;

    /**
     * 根据课程id查询当前用户的学习资格
     *
     * @param courseId 课程id
     * @return 学习资格
     */
    @Override
    public XcCourseTablesDTO getLearningQualification(Long courseId) {
        SecurityUtil.XcUser user = SecurityUtil.getUser();
        return getLearningQualification(courseId, Objects.requireNonNull(user).getId());
    }

    /**
     * 根据课程id和用户id查询学习资格
     *
     * @param courseId 课程id
     * @param userId   用户id
     * @return 学习资格
     */
    @Override
    public XcCourseTablesDTO getLearningQualification(Long courseId, String userId) {
        // 0. 查询课程表记录和选课记录
        XcCourseTables courseTables = lambdaQuery()
                .eq(XcCourseTables::getCourseId, courseId)
                .eq(XcCourseTables::getUserId, userId)
                .one();
        XcCourseTablesDTO xcCourseTablesDTO = BeanUtil.copyProperties(courseTables, XcCourseTablesDTO.class);
        XcChooseCourse xcChooseCourse = xcChooseCourseMapper.selectOne(new LambdaQueryWrapper<XcChooseCourse>()
                .eq(XcChooseCourse::getCourseId, courseId)
                .eq(XcChooseCourse::getUserId, userId));
        // 1. 如果查不到该用户的该课程,则返回未选
        if (courseTables == null)
            return new XcCourseTablesDTO().setLearnStatus(LearningQualificationConstant.NOT_CHOOSE_OR_NOT_PAY);
        // 2. 如果是免费课程
        if (LearningOrderTypeConstant.FREE.equals(courseTables.getCourseType())) {
            // 2.1 如果未过期,则返回正常学习
            if (LocalDateTime.now().isBefore(courseTables.getValidtimeEnd()))
                return xcCourseTablesDTO.setLearnStatus(LearningQualificationConstant.NORMAL_LEARNING);
                // 2.2 如果已过期,则返回需要申请续期
            else return xcCourseTablesDTO.setLearnStatus(LearningQualificationConstant.EXPIRED_NEED_APPLY_OR_REPAY);
        }
        // 3. 如果是收费课程
        else {
            // 3.1 如果已支付
            if (LearningChooseCourseStatusConstant.CHOOSE_COURSE_SUCCESS.equals(xcChooseCourse.getStatus())) {
                // 3.1.1 如果未过期,则返回正常学习
                if (LocalDateTime.now().isBefore(courseTables.getValidtimeEnd()))
                    return xcCourseTablesDTO.setLearnStatus(LearningQualificationConstant.NORMAL_LEARNING);
                    // 3.1.2 如果已过期,则返回需要重新支付
                else return xcCourseTablesDTO.setLearnStatus(LearningQualificationConstant.EXPIRED_NEED_APPLY_OR_REPAY);
            }
            // 3.2 如果未支付,则返回需要支付
            else return xcCourseTablesDTO.setLearnStatus(LearningQualificationConstant.NOT_CHOOSE_OR_NOT_PAY);
        }
    }

    /**
     * 我的课程表
     *
     * @param params 查询条件
     * @return 分页数据
     */
    @Override
    public PageResult<XcCourseTables> myCourseTable(MyCourseTableParams params) {
        SecurityUtil.XcUser user = SecurityUtil.getUser();
        // 1. 构建分页条件
        Page<XcCourseTables> page = new Page<>(params.getPageNo(), params.getPageSize());
        // 2. 构建排序条件
        ArrayList<OrderItem> orderItems = new ArrayList<>();
        if (StrUtil.isNotBlank(params.getSortType())) {
            switch (params.getSortType()) {
                // 2.1 按照最近学习的课程排序
                case "1":
                    orderItems.add(OrderItem.desc("update_date"));
                    break;
                // 2.2 按照课程的创建时间排序
                case "2":
                    orderItems.add(OrderItem.desc("create_date"));
                    break;
                default:
                    break;
            }
        }
        if (StrUtil.isNotBlank(params.getExpiresType())) {
            switch (params.getExpiresType()) {
                // 2.3 快过期了隐含按照到期时间升序排序
                case "1":
                    orderItems.add(OrderItem.asc("validtime_end"));
                    break;
                // 2.4 已过期的隐含按照到期时间降序排序
                case "2":
                    orderItems.add(OrderItem.desc("validtime_end"));
                    break;
                default:
                    break;
            }
        }
        page.addOrder(orderItems);
        // 3. 查询分页数据
        Page<XcCourseTables> tablesPage = lambdaQuery()
                // 3.1 查询当前用户的课程表
                .eq(XcCourseTables::getUserId, Objects.requireNonNull(user).getId())
                // 3.2 是否是免费课程
                .eq(StrUtil.isNotBlank(params.getCourseType()), XcCourseTables::getCourseType, params.getCourseType())
                // 3.3 快过期的课程
                .gt(StrUtil.isNotBlank(params.getExpiresType()) && params.getExpiresType().equals("1"), XcCourseTables::getValidtimeEnd, LocalDateTime.now())
                .lt(StrUtil.isNotBlank(params.getExpiresType()) && params.getExpiresType().equals("1"), XcCourseTables::getValidtimeEnd, LocalDateTime.now().plusDays(REMAIN_EXPIRE_DAYS))
                // 3.4 已过期的课程
                .lt(StrUtil.isNotBlank(params.getExpiresType()) && params.getExpiresType().equals("2"), XcCourseTables::getValidtimeEnd, LocalDateTime.now())
                .page(page);
        return new PageResult<>(tablesPage.getRecords(), tablesPage.getTotal(), params.getPageNo(), params.getPageSize());
    }

    /**
     * 根据用户id查询我的课程表
     *
     * @param userId 用户id
     * @return 我的课程表
     */
    @Override
    public List<XcCourseTables> getCourseTables(String userId) {
        return lambdaQuery()
                .eq(XcCourseTables::getUserId, userId)
                .gt(XcCourseTables::getValidtimeEnd, LocalDateTime.now())
                .orderByDesc(XcCourseTables::getUpdateDate)
                .list();
    }
}
